﻿namespace OutLook.Model.Domains
{
    using System;
    using System.Collections.Generic;
    using OutLook.Model.Infrastructure;
    using System.Xml.Serialization;
    using System.Linq;
    using System.Data;
    using Microsoft.SqlServer.Server;
    using OutLook.Model.Domains;
    using System.Text;
    using OutLook.Properties.Calc;
    using System.Runtime.Serialization;

    /// <summary>
    /// Domain Load
    /// </summary>
    [DataContract]
    public class Load : IAssignable, IDisposable, IValidatable
    {
        #region Constructors

        /// <summary>
        /// TODO:Nastya
        /// </summary>
        public Load() { }

        /// <summary>
        /// TODO:Nastya
        /// </summary>
        /// <param name="title">TODO:Nastya</param>
        /// <param name="chargeToLoad">TODO:Nastya</param>
        /// <param name="typeOfWeight">TODO:Nastya</param>
        /// <param name="production">TODO:Nastya</param>
        public Load(string title, IEnumerable<ChargeRowToLoad> chargeToLoad, string typeOfWeight,
                    double production)
        {
            m_LoadInfo = LoadData.Create(title, chargeToLoad, typeOfWeight, production);
        }

        /// <summary>
        /// TODO:Nastya
        /// </summary>
        /// <param name="title">TODO:Nastya</param>
        /// <param name="chargeToLoad">TODO:Nastya</param>
        /// <param name="lossToLoad">TODO:Nastya</param>
        /// <param name="typeOfWeight">TODO:Nastya</param>
        /// <param name="production">TODO:Nastya</param>
        public Load(string title, IEnumerable<ChargeRowToLoad> chargeToLoad,
                     IEnumerable<LossRowToLoad> lossToLoad, string typeOfWeight, double production)
        {
            m_LoadInfo = LoadData.Create(title, chargeToLoad, lossToLoad, typeOfWeight, production);
        }

        /// <summary>
        /// TODO:Nastya
        /// </summary>
        /// <param name="obj">TODO:Nastya</param>
        public Load(LoadData obj)
        {
            m_LoadInfo = LoadData.Create(obj);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Load information object 
        /// </summary>
        [DataMember(Order = 1)]
        public LoadData LoadInfo
        {
            get { return m_LoadInfo; }
            private set { m_LoadInfo = value; }
        }

        /// <summary>
        /// Total Load Charge chemical elements of each chemical composition in Load for charge
        /// </summary>
        [DataMember(Order = 2)]
        public List<ChemicalСombination> TotalLoadChargeChemicalElements
        {
            get;
            set;
        }

        /// <summary>
        /// Total Load Weight
        /// </summary>
        [DataMember(Order = 3)]
        public double TotalLoadWeight { get; set; }

        /// <summary>
        /// Fe2O3 contains in Load
        /// </summary>
        [DataMember(Order = 4)]
        public double Fe2O3 { get; set; }

        /// <summary>
        /// Fe contains in Load
        /// </summary>
        [DataMember(Order = 5)]
        public double TotalFe { get; set; }

        /// <summary>
        /// De Load (calculation property)
        /// </summary>
        [DataMember(Order = 6)]
        public double De { get; set; }

        /// <summary>
        /// Ro Load (calculation property)
        /// </summary>
        [DataMember(Order = 7)]
        public double Ro { get; set; }

        /// <summary>
        /// Basic 1 (CaO/SiO2) of load (calculation property)
        /// </summary>
        public double Basic1 { get; set; }

        /// <summary>
        /// Basic 2 ((CaO+MgO)/SiO2) of load (calculation property)
        /// </summary>
        public double Basic2 { get; set; }

        /// <summary>
        /// Basic 3 (Al2O3/MgO) of load (calculation property)
        /// </summary>
        public double Basic3 { get; set; }

        /// <summary>
        /// Ore capacity of load (calculation property)
        /// </summary>
        [DataMember(Order = 8)]
        public double OreCapacity { get; set; }

        /// <summary>
        /// Total chemical composition of each component in Load for loss
        /// </summary>
        [DataMember(Order = 9)]
        public KeyValuePair<string, double> TotalLoadLoss { get; set; }

        /// <summary>
        /// Total chemical composition of each component in Load for charge whithout loss
        /// </summary>
        [DataMember(Order = 10)]
        public KeyValuePair<string, double> TotalLoadChargeWithoutLoss { get; set; }

        /// <summary>
        /// Total chemical composition of each component in Load for bad components of charge
        /// </summary>
        [DataMember(Order = 11)]
        public KeyValuePair<string, double> TotalLoadBadCharge { get; set; }

        /// <summary>
        /// Total chemical composition of each component in Load for bad components of charge whithout loss
        /// </summary>
        [DataMember(Order = 12)]
        public KeyValuePair<string, double> TotalLoadBadChargeWithoutLoss { get; set; }

        #endregion

        #region IAssignable Implementation

        /// <summary>
        /// Assigns values of current load information object to the argument object
        /// </summary>
        /// <param name="obj">Object to assign to</param>
        /// <exception cref="ArgumentNullException">If object to assign to is nullable</exception>
        /// <exception cref="NotSupportedException">If object to assign to doesn't fit</exception>
        public void AssignTo(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException();

            if (obj is Load)
            {
                Load load = obj as Load;
                load.LoadInfo = m_LoadInfo;

                return;
            }

            throw new NotSupportedException();
        }

        #endregion

        #region IDisposable Implementation

        /// <summary>
        /// Releazes resources
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releazes managed and unmanaged resources
        /// </summary>
        /// <param name="managedDispose">TODO: Yuliya</param>
        private void Dispose(bool managedDispose)
        {
            if (m_Dispose)
                return;

            if (managedDispose)
            {
                ///TODO: dispose managed
            }

            m_LoadInfo.Dispose();

            m_Dispose = true;
        }

        #endregion

        #region IValidatable Implementation

        /// <summary>
        /// Validates Load Data
        /// </summary>
        /// <returns>True - if current Load Data is valid, otherwise - false</returns>
        public bool Validate()
        {
            return m_LoadInfo.Validate();
        }

        #endregion

        #region IEquatable by diferent criterias

        /// <summary>
        /// Compares Weight of each composition  in current LoadData with Weight of each composition in another one
        /// </summary>
        /// <param name="other">Another LoadData</param>
        /// <returns>True - If Weight of each composition in current Load and Weight of each composition in another one are equal, otherwise -False</returns>
        public bool EqualsWeight(List<ChemicalСombination> other)
        {
            bool result = true;
            int EqualElements = 0;
            foreach (ChemicalСombination comp in TotalLoadChargeChemicalElements)
            {
                foreach (ChemicalСombination othercomp in other)
                {
                    if (comp.Element == othercomp.Element)
                    {
                        EqualElements++;
                        if (comp.Weight != othercomp.Weight)
                        {
                            result = false;
                            break;
                        }
                    }
                }
            }
            if (EqualElements != TotalLoadChargeChemicalElements.Count)
            {
                result = false;
            }
            return result;
        }

        /// <summary>
        /// TODO:---
        /// </summary>
        /// <param name="other">TODO:---</param>
        /// <returns>TODO:---</returns>
        public bool EqualsPercent(List<ChemicalСombination> other)
        {
            bool result = true;
            int EqualElements = 0;
            foreach (ChemicalСombination comp in TotalLoadChargeChemicalElements)
            {
                foreach (ChemicalСombination othercomp in other)
                {
                    if (comp.Element == othercomp.Element)
                    {
                        EqualElements++;
                        if (comp.Percentage != othercomp.Percentage)
                        {
                            result = false;
                            break;
                        }
                    }
                }
            }
            if (EqualElements != TotalLoadChargeChemicalElements.Count)
            {
                result = false;
            }
            return result;
        }

        #endregion       

        #region Fields

        private LoadData m_LoadInfo = LoadData.Create();
        private bool m_Dispose = false;

        #endregion
    }
}
